package com.smart.community.commons.service.impl;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.community.commons.dto.SystemLogQueryDTO;
import com.smart.community.commons.entity.SystemLog;
import com.smart.community.commons.mapper.SystemLogMapper;
import com.smart.community.commons.result.PageResult;
import com.smart.community.commons.service.SystemLogService;
import com.smart.community.commons.utils.RedisUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * 系统日志Service实现类
 * 生产环境高标准优化版本
 * 
 * @author Wu.Liang
 * @since 2025-01-30
 * @version 2.0.0
 */
@Slf4j
@Service
public class SystemLogServiceImpl extends ServiceImpl<SystemLogMapper, SystemLog> implements SystemLogService
{
    
    @Autowired
    private SystemLogMapper systemLogMapper;
    
    @Autowired
    private RedisUtil redisUtil;
    
    // 缓存配置
    private static final String CACHE_PREFIX = "system_log";
    private static final String PAGE_CACHE_PREFIX = CACHE_PREFIX + ":page:";
    private static final String USER_CACHE_PREFIX = CACHE_PREFIX + ":user:";
    private static final String COMPANY_CACHE_PREFIX = CACHE_PREFIX + ":company:";
    private static final long CACHE_EXPIRE_TIME = 1800; // 30分钟
    
    @Override
    public PageResult<SystemLog> getSystemLogPage(SystemLogQueryDTO queryDTO) throws Exception {
        log.debug("执行系统日志分页查询，查询条件：{}", queryDTO);
        
        try {
            // 生成缓存键
            String cacheKey = PAGE_CACHE_PREFIX + generateCacheKey(queryDTO);
            
            // 尝试从缓存获取
            Object cachedResult = redisUtil.get(cacheKey);
            if (cachedResult instanceof PageResult) {
                @SuppressWarnings("unchecked")
                PageResult<SystemLog> result = (PageResult<SystemLog>) cachedResult;
                log.debug("从缓存获取系统日志分页数据");
                return result;
            }
            
            // 创建分页对象
            Page<SystemLog> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());
            
            // 执行分页查询
            IPage<SystemLog> pageResult = systemLogMapper.selectSystemLogPage(page, queryDTO);
            
            // 构建返回结果
            PageResult<SystemLog> result = new PageResult<>();
            result.setCurrent((int) pageResult.getCurrent());
            result.setSize((int) pageResult.getSize());
            result.setTotal(pageResult.getTotal());
            result.setPages((int) pageResult.getPages());
            result.setRecords(pageResult.getRecords());
            
            // 缓存结果
            try {
                redisUtil.set(cacheKey, result, CACHE_EXPIRE_TIME, TimeUnit.SECONDS);
                log.debug("系统日志分页数据已缓存");
            } catch (Exception e) {
                log.warn("缓存系统日志分页数据失败", e);
            }
            
            return result;
        } catch (Exception e) {
            log.error("系统日志分页查询失败", e);
            throw e;
        }
    }
    
    @Override
    public PageResult<SystemLog> getSystemLogPageWithPermission(SystemLogQueryDTO queryDTO) throws Exception {
        // 基础的分页查询，具体的数据权限控制由调用方实现
        // 这里只提供基础的查询功能，避免在commons模块中引入feign依赖
        log.debug("执行基础系统日志查询，具体权限控制由调用方实现");
        return getSystemLogPage(queryDTO);
    }
    
    @Override
    public List<SystemLog> getSystemLogListForExport(SystemLogQueryDTO queryDTO) throws Exception {
        log.debug("获取系统日志列表用于导出，查询条件：{}", queryDTO);
        
        try {
            // 创建分页对象，设置较大的页面大小以获取所有数据
            Page<SystemLog> page = new Page<>(1, 10000);
            
            // 执行查询
            IPage<SystemLog> pageResult = systemLogMapper.selectSystemLogPage(page, queryDTO);
            
            return pageResult.getRecords();
        } catch (Exception e) {
            log.error("获取系统日志列表用于导出失败", e);
            throw e;
        }
    }
    
    @Override
    public void clearSystemLog() throws Exception {
        log.info("开始清空系统日志");
        
        try {
            // 使用软删除，将deleted字段设置为1
            int deletedCount = systemLogMapper.delete(null);
            
            // 清除相关缓存
            clearSystemLogCache();
            
            log.info("系统日志清空完成，共清空{}条记录", deletedCount);
        } catch (Exception e) {
            log.error("清空系统日志失败", e);
            throw e;
        }
    }
    
    /**
     * 创建空的分页结果
     */
    private PageResult<SystemLog> createEmptyPageResult(SystemLogQueryDTO queryDTO) {
        PageResult<SystemLog> result = new PageResult<>();
        result.setCurrent(queryDTO.getCurrent());
        result.setSize(queryDTO.getSize());
        result.setTotal(0L);
        result.setPages(0);
        result.setRecords(Collections.emptyList());
        return result;
    }
    
    @Override
    public PageResult<SystemLog> getSystemLogByUserId(Long userId, Integer current, Integer size) throws Exception {
        log.debug("根据用户ID查询系统日志，用户ID：{}，页码：{}，页大小：{}", userId, current, size);
        
        try {
            // 生成缓存键
            String cacheKey = USER_CACHE_PREFIX + userId + ":" + current + ":" + size;
            
            // 尝试从缓存获取
            Object cachedResult = redisUtil.get(cacheKey);
            if (cachedResult instanceof PageResult) {
                @SuppressWarnings("unchecked")
                PageResult<SystemLog> result = (PageResult<SystemLog>) cachedResult;
                log.debug("从缓存获取用户系统日志数据");
                return result;
            }
            
            // 创建分页对象
            Page<SystemLog> page = new Page<>(current, size);
            
            // 构建查询条件
            SystemLogQueryDTO queryDTO = new SystemLogQueryDTO();
            queryDTO.setCurrent(current);
            queryDTO.setSize(size);
            // 设置用户ID查询条件
            queryDTO.setUsername(userId.toString()); // 这里需要根据实际字段调整
            
            // 执行分页查询
            IPage<SystemLog> pageResult = systemLogMapper.selectSystemLogPage(page, queryDTO);
            
            // 构建返回结果
            PageResult<SystemLog> result = new PageResult<>();
            result.setCurrent((int) pageResult.getCurrent());
            result.setSize((int) pageResult.getSize());
            result.setTotal(pageResult.getTotal());
            result.setPages((int) pageResult.getPages());
            result.setRecords(pageResult.getRecords());
            
            // 缓存结果
            try {
                redisUtil.set(cacheKey, result, CACHE_EXPIRE_TIME, TimeUnit.SECONDS);
                log.debug("用户系统日志数据已缓存");
            } catch (Exception e) {
                log.warn("缓存用户系统日志数据失败", e);
            }
            
            return result;
        } catch (Exception e) {
            log.error("根据用户ID查询系统日志失败，用户ID：{}", userId, e);
            throw e;
        }
    }
    
    @Override
    public PageResult<SystemLog> getSystemLogByPropertyCompanyId(Long propertyCompanyId, Integer current, Integer size) throws Exception {
        log.debug("根据物业公司ID查询系统日志，物业公司ID：{}，页码：{}，页大小：{}", propertyCompanyId, current, size);
        
        try {
            // 生成缓存键
            String cacheKey = COMPANY_CACHE_PREFIX + propertyCompanyId + ":" + current + ":" + size;
            
            // 尝试从缓存获取
            Object cachedResult = redisUtil.get(cacheKey);
            if (cachedResult instanceof PageResult) {
                @SuppressWarnings("unchecked")
                PageResult<SystemLog> result = (PageResult<SystemLog>) cachedResult;
                log.debug("从缓存获取物业公司系统日志数据");
                return result;
            }
            
            // 创建分页对象
            Page<SystemLog> page = new Page<>(current, size);
            
            // 使用专门的物业公司ID分页查询方法
            IPage<SystemLog> pageResult = systemLogMapper.selectSystemLogPageByPropertyCompanyId(page, propertyCompanyId);
            
            // 构建返回结果
            PageResult<SystemLog> result = new PageResult<>();
            result.setCurrent((int) pageResult.getCurrent());
            result.setSize((int) pageResult.getSize());
            result.setTotal(pageResult.getTotal());
            result.setPages((int) pageResult.getPages());
            result.setRecords(pageResult.getRecords());
            
            // 缓存结果
            try {
                redisUtil.set(cacheKey, result, CACHE_EXPIRE_TIME, TimeUnit.SECONDS);
                log.debug("物业公司系统日志数据已缓存");
            } catch (Exception e) {
                log.warn("缓存物业公司系统日志数据失败", e);
            }
            
            return result;
        } catch (Exception e) {
            log.error("根据物业公司ID查询系统日志失败，物业公司ID：{}", propertyCompanyId, e);
            throw e;
        }
    }
    
    @Override
    public PageResult<SystemLog> getSystemLogByPropertyCompanyIds(List<Long> propertyCompanyIds, Integer current, Integer size) throws Exception {
        log.debug("根据多个物业公司ID查询系统日志，物业公司ID列表：{}，页码：{}，页大小：{}", propertyCompanyIds, current, size);
        
        try {
            // 生成缓存键
            String cacheKey = COMPANY_CACHE_PREFIX + "multi:" + generateListCacheKey(propertyCompanyIds) + ":" + current + ":" + size;
            
            // 尝试从缓存获取
            Object cachedResult = redisUtil.get(cacheKey);
            if (cachedResult instanceof PageResult) {
                @SuppressWarnings("unchecked")
                PageResult<SystemLog> result = (PageResult<SystemLog>) cachedResult;
                log.debug("从缓存获取多物业公司系统日志数据");
                return result;
            }
            
            // 创建分页对象
            Page<SystemLog> page = new Page<>(current, size);
            
            // 使用专门的多个物业公司ID分页查询方法
            IPage<SystemLog> pageResult = systemLogMapper.selectSystemLogPageByPropertyCompanyIds(page, propertyCompanyIds);
            
            // 构建返回结果
            PageResult<SystemLog> result = new PageResult<>();
            result.setCurrent((int) pageResult.getCurrent());
            result.setSize((int) pageResult.getSize());
            result.setTotal(pageResult.getTotal());
            result.setPages((int) pageResult.getPages());
            result.setRecords(pageResult.getRecords());
            
            // 缓存结果
            try {
                redisUtil.set(cacheKey, result, CACHE_EXPIRE_TIME, TimeUnit.SECONDS);
                log.debug("多物业公司系统日志数据已缓存");
            } catch (Exception e) {
                log.warn("缓存多物业公司系统日志数据失败", e);
            }
            
            return result;
        } catch (Exception e) {
            log.error("根据多个物业公司ID查询系统日志失败，物业公司ID列表：{}", propertyCompanyIds, e);
            throw e;
        }
    }
    
    /**
     * 生成缓存键
     * 
     * @param queryDTO 查询条件
     * @return 缓存键
     */
    private String generateCacheKey(SystemLogQueryDTO queryDTO) {
        StringBuilder keyBuilder = new StringBuilder();
        keyBuilder.append(queryDTO.getCurrent()).append("_")
                  .append(queryDTO.getSize()).append("_");
        
        if (queryDTO.getUsername() != null) {
            keyBuilder.append(queryDTO.getUsername()).append("_");
        }
        if (queryDTO.getOperationType() != null) {
            keyBuilder.append(queryDTO.getOperationType()).append("_");
        }
        if (queryDTO.getStartTime() != null) {
            keyBuilder.append(queryDTO.getStartTime().toString()).append("_");
        }
        if (queryDTO.getEndTime() != null) {
            keyBuilder.append(queryDTO.getEndTime().toString()).append("_");
        }
        
        return keyBuilder.toString();
    }
    
    /**
     * 生成列表缓存键
     * 
     * @param ids ID列表
     * @return 缓存键
     */
    private String generateListCacheKey(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return "empty";
        }
        
        StringBuilder keyBuilder = new StringBuilder();
        for (Long id : ids) {
            keyBuilder.append(id).append("_");
        }
        return keyBuilder.toString();
    }
    
    /**
     * 清除系统日志相关缓存
     */
    private void clearSystemLogCache() {
        try {
            // 清除分页缓存
            Set<String> pageKeys = redisUtil.keys(PAGE_CACHE_PREFIX + "*");
            if (pageKeys != null) {
                redisUtil.delete(pageKeys);
            }
            // 清除用户缓存
            Set<String> userKeys = redisUtil.keys(USER_CACHE_PREFIX + "*");
            if (userKeys != null) {
                redisUtil.delete(userKeys);
            }
            // 清除物业公司缓存
            Set<String> companyKeys = redisUtil.keys(COMPANY_CACHE_PREFIX + "*");
            if (companyKeys != null) {
                redisUtil.delete(companyKeys);
            }
            
            log.debug("系统日志相关缓存已清除");
        } catch (Exception e) {
            log.warn("清除系统日志缓存失败", e);
        }
    }
}
